\title{myHDL Implementation of a CIC Filter} \author{Steven K Armour} \maketitle


In [1]:
import numpy as np
np.seterr(divide='ignore', invalid='ignore')

import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
#import plotly.plotly as py
#import plotly.graph_objs as go
from sympy import *
from sympy import S; Zero=S.Zero
init_printing()


import scipy.signal as sig
%matplotlib notebook

import ipywidgets as widg



from myhdl import *
from myhdlpeek import Peeker

Preliminaries

Target Architecture size


In [2]:
BitWidth=32

Code to read back the generated Verilog(VHDL) from myHDL back into the Jupyter Notebook


In [3]:
#helper  functions to read in the .v and .vhd generated files into python
def VerilogTextReader(loc, printresult=True):
    with open(f'{loc}.v', 'r') as vText:
        VerilogText=vText.read()
    if printresult:
        print(f'***Verilog modual from {loc}.v***\n\n', VerilogText)
    return VerilogText

def VHDLTextReader(loc, printresult=True):
    with open(f'{loc}.vhd', 'r') as vText:
        VerilogText=vText.read()
    if printresult:
        print(f'***VHDL modual from {loc}.vhd***\n\n', VerilogText)
    return VerilogText

Z-Transform preliminary math and Z-Plane graphing code


In [4]:
z, r, DisAng=symbols('z, r, Omega')
zFunc=Eq(z, r*exp(1j*DisAng)); zFunc


Out[4]:
$$z = r e^{1.0 i \Omega}$$

In [5]:
zFuncN=lambdify((r, DisAng), zFunc.rhs, dummify=False)

zr=np.arange(-1.5, 1.5+.03, .03); zi=np.copy(zr)
zR, zI=np.meshgrid(zr, zi)
zN=zR+1j*zI

rN=1.0
AngThetaN=np.arange(0, 1+.005, .005)*2*np.pi
zAtR1=zFuncN(rN, AngThetaN)

In [6]:
%matplotlib notebook





def Zplot(zR, zI, HzNMag, HzAtR1NMag, HzNPhase, HzAtR1NPhase, title):
    
    
    fig = plt.figure()

    #plot the z space mag
    axZmag = fig.add_subplot(221, projection='3d')
    Mags=axZmag.plot_surface(zR, zI, HzNMag, cmap=plt.get_cmap('tab20'))
    axZmag.plot(np.real(zAtR1), np.imag(zAtR1), HzAtR1NMag, 'r-', label='r=1')
    axZmag.set_xlabel('Re'); axZmag.set_ylabel('Im'); axZmag.set_zlabel('Mag')
    axZmag.legend(loc='best')
    fig.colorbar(Mags)

    #plot the z space phase
    axZph = fig.add_subplot(222, projection='3d')
    Phase=axZph.plot_surface(zR, zI, HzNPhase, cmap=plt.get_cmap('tab20'))
    axZph.plot(np.real(zAtR1), np.imag(zAtR1), HzAtR1NPhase, 'r-', label='r=1')
    axZph.set_xlabel('Re'); axZph.set_ylabel('Im'); axZph.set_zlabel('Phase')
    axZph.legend(loc='best')
    fig.colorbar(Phase)


    axBodeM=fig.add_subplot(212)
    Mline=axBodeM.plot(AngThetaN, HzAtR1NMag, label='FTMag')
    axBodeM.set_ylabel('Mag')

    axBodeP=axBodeM.twinx()
    Pline=axBodeP.plot(AngThetaN, np.rad2deg(HzAtR1NPhase), 'g--', label='FTPhase')
    axBodeP.set_ylabel('Phase [deg]')
    axBodeP.set_xlabel('Ang')


    lns = Mline+Pline
    labs = [l.get_label() for l in lns]
    axBodeP.legend(lns, labs, loc='best')
    
    fig.suptitle(title)
    fig.show()

To improve:

  1. Come up with good test bench for CIC
  2. Record all test to DataFrame and z-transform results

  3. add widgets

  4. Clean up theory

Delay

Theory


In [7]:
M=symbols('M')
DelayH=z**(-M); DelayH


Out[7]:
$$z^{- M}$$

In [8]:
DelaySupH=simplify(DelayH.subs(zFunc.lhs, zFunc.rhs)); DelaySupH


Out[8]:
$$\left(r e^{1.0 i \Omega}\right)^{- M}$$

In [9]:
DelaySupH=simplify(DelaySupH.subs(r, 1)); DelaySupH


Out[9]:
$$\left(e^{1.0 i \Omega}\right)^{- M}$$

In [10]:
DelayHN=lambdify((z, M), DelayH, dummify=False)
Mvalue=2
HzN=DelayHN(zN, M=Mvalue); HzN.shape
HzNMag=np.abs(HzN); HzNPhase=np.angle(HzN)

HAtR1=zFuncN(rN, AngThetaN)
HzAtR1N=DelayHN(zAtR1, M=Mvalue)
HzAtR1NMag=np.abs(HzAtR1N); HzAtR1NPhase=np.angle(HzAtR1N)

In [11]:
def DelayExplorer(M=1):
    Mvalue=M
    
    HzN=DelayHN(zN, M=Mvalue); HzN.shape
    HzNMag=np.abs(HzN); HzNPhase=np.angle(HzN)

    HAtR1=zFuncN(rN, AngThetaN)
    HzAtR1N=DelayHN(zAtR1, M=Mvalue)
    HzAtR1NMag=np.abs(HzAtR1N); HzAtR1NPhase=np.angle(HzAtR1N)
    Zplot(zR, zI, HzNMag, HzAtR1NMag, HzNPhase, HzAtR1NPhase, 
          f'z Delay order M={M}')

In [12]:
# will add widgets for interative later
DelayExplorer(M=1)


myHDL implementation


In [13]:
def Delay(x, y, ena_in, clk):
    '''
        Z delay bulding block for a CIC filter
        
        Inputs:
            x (data): the x(n) data in feed
            ------------------------
            ena_in (bool): the exstiror calc hold input. calc is done only if 
            `ena_in` is True
            
            clk(bool): clock feed
            rst(bool): reset feed
        
        Outputs:
            y (data):  the y(n+1) output of y(n+1)=x(n)
            
    '''
    @always(clk. posedge)
    def logic():
        if ena_in:
            y.next=x
    return logic

myHDL Testing


In [14]:
Peeker.clear()

x=Signal(modbv(0)[BitWidth:]); Peeker(x, 'x')
y=Signal(modbv(0)[BitWidth:]); Peeker(y, 'y')

ena_in, clk=[Signal(bool(0)) for  _ in range(2)]
Peeker(ena_in, 'ena_in'); Peeker(clk, 'clk')

DUT=Delay(x, y, ena_in, clk)

DateCol=pd.DataFrame(columns=['x', 'y', 'ena_in'])

def Delay_TB():
    
    @always(delay(1))  ## delay in nano seconds
    def clkGen():
        clk.next = not clk
        
    @instance
    def stimulus():
        Tested_ena=False
        count=0
        while 1:
            
            if Tested_ena==False and count<=2:
                print(f'Tested_ena: {Tested_ena}, count:{count}')
            elif Tested_ena==False and count>2:
                print(f'Tested_ena: {Tested_ena}, count:{count}')

                ena_in.next=True
                Tested_ena=True
                x.next=0
           
            
            if Tested_ena  and count>2:
                x.next=x+1
            
            if count> 2*BitWidth:
                raise StopSimulation
            
            DateCol.loc[count]=[int(x),int(y), int(ena_in)]
            
            count+=1
            yield clk.posedge
                
                
            
    return instances()
sim = Simulation(DUT, Delay_TB(), *Peeker.instances()).run()


Tested_ena: False, count:0
Tested_ena: False, count:1
Tested_ena: False, count:2
Tested_ena: False, count:3

In [15]:
Peeker.to_wavedrom(start_time=0, stop_time=40, tock=True)


To Verilog


In [16]:
x=Signal(modbv(0)[BitWidth:])
y=Signal(modbv(0)[BitWidth:])
ena_in, clk=[Signal(bool(0)) for  _ in range(2)]
toVerilog(Delay, x, y, ena_in, clk)
VerilogTextReader('Delay');


***Verilog modual from Delay.v***

 // File: Delay.v
// Generated by MyHDL 0.9.0
// Date: Mon Feb 26 19:21:50 2018


`timescale 1ns/10ps

module Delay (
    x,
    y,
    ena_in,
    clk
);
// Z delay bulding block for a CIC filter
// 
// Inputs:
//     x (data): the x(n) data in feed
//     ------------------------
//     ena_in (bool): the exstiror calc hold input. calc is done only if 
//     `ena_in` is True
//     
//     clk(bool): clock feed
//     rst(bool): reset feed
// 
// Outputs:
//     y (data):  the y(n+1) output of y(n+1)=x(n)
//     

input [31:0] x;
output [31:0] y;
reg [31:0] y;
input ena_in;
input clk;






always @(posedge clk) begin: DELAY_LOGIC
    if (ena_in) begin
        y <= x;
    end
end

endmodule

Comb

Theory


In [17]:
CombH=1-z**(-M); CombH


Out[17]:
$$1 - z^{- M}$$

In [18]:
CombSupH=simplify(CombH.subs(zFunc.lhs, zFunc.rhs)); CombSupH


Out[18]:
$$1 - \left(r e^{1.0 i \Omega}\right)^{- M}$$

In [19]:
CombSupH=simplify(CombSupH.subs(r, 1)); CombSupH


Out[19]:
$$1 - \left(e^{1.0 i \Omega}\right)^{- M}$$

In [20]:
CombHN=lambdify((z, M), CombH, dummify=False)
def CombEx(M=2):
    Mvalue=M
    HzN=CombHN(zN, M=Mvalue); HzN.shape
    HzNMag=np.abs(HzN); HzNPhase=np.angle(HzN)

    HAtR1=zFuncN(rN, AngThetaN)
    HzAtR1N=DelayHN(zAtR1, M=Mvalue)
    HzAtR1NMag=np.abs(HzAtR1N); HzAtR1NPhase=np.angle(HzAtR1N)

    Zplot(zR, zI, HzNMag, HzAtR1NMag, HzNPhase, HzAtR1NPhase, 
          f'Comb of Order M={Mvalue}')
CombEx(M=2)


myHDL implementation


In [21]:
def Comb(x, y, ena_in, ena_out, clk, rst, M=2):
    '''
        the comb section of  a CIC filter relaying on `Delay` to create
        the Z dealy blocks
        
        Inputs:
            x (data): the x(n) data in feed
            ------------------------
            ena_in (bool): the exstiror calc hold input. calc is done only if 
            `ena_in` is True
            
            clk(bool): clock feed
            rst(bool): reset feed
        
        Outputs:
            y (data):  the y(n) output of y(n)=y(n-1)+x(n)
            ----------------------
            ena_out: the exstior calc hold output. will be false if 
            `ena_in` is False
        Parm:
            M: the nuumber of Z delays for this comb section
    '''
    
    
    #stage the the Zdelays
    Zdelay_i=[None for i in range(M)]
    
    #Parmters for sizeing the 2's comp interdaley wires
    WordLen_1=len(x)-1
    WireGuage=2**WordLen_1
    
    # Create the wiring between the delays
    Zwire_ij=[Signal(modbv(0, min=-WireGuage, max=WireGuage)) for j in range(M)]

    #instainsate and wire togather the Zdelays
    for i in range(M):
        if i==0:
            Zdelay_i[i]=Delay(x, Zwire_ij[i], ena_in, clk)
        else:
            Zdelay_i[i]=Delay(Zwire_ij[i-1], Zwire_ij[i], ena_in, clk)
    
    #make the last delay output unieq x(M-1)
    subx=Zwire_ij[M-1]
    
    @always(clk.posedge)
    def logc():
        if rst:
            y.next=0
        else:
            if ena_in:
                #y=x-x(M-1)
                y.next=x-subx
                ena_out.next=True
            else:
                ena_out.next=False
    return instances()

myHDL Testing


In [22]:
Peeker.clear()

x=Signal(modbv(1)[BitWidth:]); Peeker(x, 'x')
y=Signal(modbv(5)[BitWidth:]); Peeker(y, 'y')

ena_in, ena_out, clk, rst=[Signal(bool(0)) for  _ in range(4)]
Peeker(ena_in, 'ena_in'); Peeker(ena_out, 'ena_out'); Peeker(clk, 'clk'); Peeker(rst, 'rst')

DUT=Comb(x, y, ena_in, ena_out, clk, rst, M=2)

def Comb_TB():
    
    @always(delay(1))  ## delay in nano seconds
    def clkGen():
        clk.next = not clk
        
    @instance
    def stimulus():
        Tested_ena=False
        Tested_rst=False
        count=0
        while 1:
            
            if Tested_ena==False and count<=2:
                print(f'Tested_ena: {Tested_ena}, Tested_rst:{Tested_rst}, count:{count}')
            elif Tested_ena==False and count>2:
                print(f'Tested_ena: {Tested_ena}, Tested_rst:{Tested_rst}, count:{count}')

                ena_in.next=True
                Tested_ena=True
            
            if Tested_ena and Tested_rst==False:
                print(f'Tested_ena: {Tested_ena}, Tested_rst:{Tested_rst}, count:{count}')

                rst.next=True
                Tested_rst=True
            elif Tested_ena and Tested_rst and  count<=4:
                print(f'Tested_ena: {Tested_ena}, Tested_rst:{Tested_rst}, count:{count}')

                rst.next=False
                Tested_rst=True
                x.next=1
            
            if Tested_ena and Tested_rst and count>4:
                x.next=2*(x+1)
            
            if count> 2*BitWidth:
                raise StopSimulation
            count+=1
            yield clk.posedge
                
                
            
    return instances()
sim = Simulation(DUT, Comb_TB(), *Peeker.instances()).run()


Tested_ena: False, Tested_rst:False, count:0
Tested_ena: False, Tested_rst:False, count:1
Tested_ena: False, Tested_rst:False, count:2
Tested_ena: False, Tested_rst:False, count:3
Tested_ena: True, Tested_rst:False, count:3
Tested_ena: True, Tested_rst:True, count:4

In [23]:
Peeker.to_wavedrom(start_time=0, stop_time=40, tock=True)


To Verilog


In [24]:
x=Signal(modbv(1)[BitWidth:])
y=Signal(modbv(5)[BitWidth:])

ena_in, ena_out, clk, rst=[Signal(bool(0)) for  _ in range(4)]
toVerilog(Comb, x, y, ena_in, ena_out, clk, rst, M=2)
VerilogTextReader('Comb');


***Verilog modual from Comb.v***

 // File: Comb.v
// Generated by MyHDL 0.9.0
// Date: Mon Feb 26 19:22:31 2018


`timescale 1ns/10ps

module Comb (
    x,
    y,
    ena_in,
    ena_out,
    clk,
    rst
);
// the comb section of  a CIC filter relaying on `Delay` to create
// the Z dealy blocks
// 
// Inputs:
//     x (data): the x(n) data in feed
//     ------------------------
//     ena_in (bool): the exstiror calc hold input. calc is done only if 
//     `ena_in` is True
//     
//     clk(bool): clock feed
//     rst(bool): reset feed
// 
// Outputs:
//     y (data):  the y(n) output of y(n)=y(n-1)+x(n)
//     ----------------------
//     ena_out: the exstior calc hold output. will be false if 
//     `ena_in` is False
// Parm:
//     M: the nuumber of Z delays for this comb section

input [31:0] x;
output [31:0] y;
reg [31:0] y;
input ena_in;
output ena_out;
reg ena_out;
input clk;
input rst;

reg signed [31:0] subx;
reg signed [31:0] Zdelay_i_1_x;





always @(posedge clk) begin: COMB_ZDELAY_I_0_LOGIC
    if (ena_in) begin
        Zdelay_i_1_x <= x;
    end
end


always @(posedge clk) begin: COMB_ZDELAY_I_1_LOGIC
    if (ena_in) begin
        subx <= Zdelay_i_1_x;
    end
end


always @(posedge clk) begin: COMB_LOGC
    if (rst) begin
        y <= 0;
    end
    else begin
        if (ena_in) begin
            y <= ($signed({1'b0, x}) - subx);
            ena_out <= 1'b1;
        end
        else begin
            ena_out <= 1'b0;
        end
    end
end

endmodule

Integrator

Theory


In [25]:
IntegratorH=1/(1-z**-1); IntegratorH


Out[25]:
$$\frac{1}{1 - \frac{1}{z}}$$

In [26]:
IntegratorSupH=simplify(IntegratorH.subs(zFunc.lhs, zFunc.rhs))
IntegratorSupH


Out[26]:
$$\frac{r e^{1.0 i \Omega}}{r e^{1.0 i \Omega} - 1}$$

In [27]:
IntegratorSupH=simplify(IntegratorSupH.subs(r, 1))
IntegratorSupH


Out[27]:
$$\frac{e^{1.0 i \Omega}}{e^{1.0 i \Omega} - 1}$$

In [28]:
IntegratorHN=lambdify(z, IntegratorH, dummify=False)
HzN=IntegratorHN(zN); HzN.shape
HzNMag=np.abs(HzN); HzNPhase=np.angle(HzN)

HAtR1=zFuncN(rN, AngThetaN)
HzAtR1N=IntegratorHN(zAtR1)
HzAtR1NMag=np.abs(HzAtR1N); HzAtR1NPhase=np.angle(HzAtR1N)

Zplot(zR, zI, HzNMag, HzAtR1NMag, HzNPhase, HzAtR1NPhase, 'Integrator')


myHDL implementation


In [29]:
def Integrator(x, y, ena_in, ena_out, clk, rst):
    '''
        Simple Integrator/ Accumultor with exstior hold contorls as part
        of the building blocks of a CIC filter
        
        Inputs:
            x (data): the x(n) data in feed
            ------------------------
            ena_in (bool): the exstiror calc hold input. calc is done only if 
            `ena_in` is True
            
            clk(bool): clock feed
            rst(bool): reset feed
        
        Outputs:
            y (data):  the y(n) output of y(n)=y(n-1)+x(n)
            ----------------------
            ena_out: the exstior calc hold output. will be false if 
            `ena_in` is False
    '''
    @always(clk.posedge)
    def logic():
        if rst:
            y.next=0
        else:
            if ena_in:
                #y(n)=y(n-1)+x(n)
                y.next=y+x
                ena_out.next=True
            else:
                ena_out.next=False
    
    return logic

myHDL Testing


In [30]:
Peeker.clear()

x=Signal(modbv(1)[BitWidth:]); Peeker(x, 'x')
y=Signal(modbv(5)[BitWidth:]); Peeker(y, 'y')

ena_in, ena_out, clk, rst=[Signal(bool(0)) for  _ in range(4)]
Peeker(ena_in, 'ena_in'); Peeker(ena_out, 'ena_out'); Peeker(clk, 'clk'); Peeker(rst, 'rst')

DUT=Integrator(x, y, ena_in, ena_out, clk, rst)

def Integrator_TB():
    
    @always(delay(1))  ## delay in nano seconds
    def clkGen():
        clk.next = not clk
        
    @instance
    def stimulus():
        Tested_ena=False
        Tested_rst=False
        count=0
        while 1:
            
            if Tested_ena==False and count<=2:
                print(f'Tested_ena: {Tested_ena}, Tested_rst:{Tested_rst}, count:{count}')
            elif Tested_ena==False and count>2:
                print(f'Tested_ena: {Tested_ena}, Tested_rst:{Tested_rst}, count:{count}')

                ena_in.next=True
                Tested_ena=True
            
            if Tested_ena and Tested_rst==False:
                print(f'Tested_ena: {Tested_ena}, Tested_rst:{Tested_rst}, count:{count}')

                rst.next=True
                Tested_rst=True
            elif Tested_ena and Tested_rst and  count<=4:
                print(f'Tested_ena: {Tested_ena}, Tested_rst:{Tested_rst}, count:{count}')

                rst.next=False
                Tested_rst=True
                x.next=0
            
            if Tested_ena and Tested_rst and count>4:
                x.next=x+1
            
            if count> 2*BitWidth:
                raise StopSimulation
            count+=1
            yield clk.posedge
                
                
            
    return instances()
sim = Simulation(DUT, Integrator_TB(), *Peeker.instances()).run()


Tested_ena: False, Tested_rst:False, count:0
Tested_ena: False, Tested_rst:False, count:1
Tested_ena: False, Tested_rst:False, count:2
Tested_ena: False, Tested_rst:False, count:3
Tested_ena: True, Tested_rst:False, count:3
Tested_ena: True, Tested_rst:True, count:4

In [31]:
Peeker.to_wavedrom(start_time=0, stop_time=40, tock=True)


To Verilog


In [32]:
x=Signal(modbv(1)[BitWidth:])
y=Signal(modbv(5)[BitWidth:])

ena_in, ena_out, clk, rst=[Signal(bool(0)) for  _ in range(4)]

toVerilog(Integrator, x, y, ena_in, ena_out, clk, rst)
VerilogTextReader('Integrator');


***Verilog modual from Integrator.v***

 // File: Integrator.v
// Generated by MyHDL 0.9.0
// Date: Mon Feb 26 19:24:35 2018


`timescale 1ns/10ps

module Integrator (
    x,
    y,
    ena_in,
    ena_out,
    clk,
    rst
);
// Simple Integrator/ Accumultor with exstior hold contorls as part
// of the building blocks of a CIC filter
// 
// Inputs:
//     x (data): the x(n) data in feed
//     ------------------------
//     ena_in (bool): the exstiror calc hold input. calc is done only if 
//     `ena_in` is True
//     
//     clk(bool): clock feed
//     rst(bool): reset feed
// 
// Outputs:
//     y (data):  the y(n) output of y(n)=y(n-1)+x(n)
//     ----------------------
//     ena_out: the exstior calc hold output. will be false if 
//     `ena_in` is False

input [31:0] x;
output [31:0] y;
reg [31:0] y;
input ena_in;
output ena_out;
reg ena_out;
input clk;
input rst;






always @(posedge clk) begin: INTEGRATOR_LOGIC
    if (rst) begin
        y <= 0;
    end
    else begin
        if (ena_in) begin
            y <= (y + x);
            ena_out <= 1'b1;
        end
        else begin
            ena_out <= 1'b0;
        end
    end
end

endmodule

** ToVerilogWarning: Output port is read internally: y

Decimator

Theory

$$y(n)=x(Rn)$$

In [33]:
R, k=symbols('R, k')
X=Function('X')(z); X


Out[33]:
$$X{\left (z \right )}$$

In [34]:
Decimator=summation(X.subs(z, z**(1/R) *exp(2j*pi*k/R)), (k, 0, R-1))/R
Decimator


Out[34]:
$$\frac{1}{R} \sum_{k=0}^{R - 1} X{\left (z^{\frac{1}{R}} e^{\frac{2.0 \pi}{R} i k} \right )}$$

In [35]:
Decimator=simplify(Decimator.subs(zFunc.lhs, zFunc.rhs))
Decimator


Out[35]:
$$\frac{1}{R} \sum_{k=0}^{R - 1} X{\left (\left(r e^{1.0 i \Omega}\right)^{\frac{1}{R}} e^{\frac{2.0 \pi}{R} i k} \right )}$$

In [36]:
Decimator.subs(r, 1)


Out[36]:
$$\frac{1}{R} \sum_{k=0}^{R - 1} X{\left (\left(e^{1.0 i \Omega}\right)^{\frac{1}{R}} e^{\frac{2.0 \pi}{R} i k} \right )}$$

myHDL implementation


In [37]:
def Decimator(x, y, ena_in, ena_out, clk, rst, R=8):
    '''
        A decimation (down sampling) section for a CIC filter
        
        Inputs:
            x (data): the x(n) data in feed
            ------------------------
            ena_in (bool): the exstiror calc hold input. calc is done only if 
            `ena_in` is True
            
            clk(bool): clock feed
            rst(bool): reset feed
        
        Outputs:
            y (data):  the y(n) output 
            ----------------------
            ena_out: the exstior calc hold output. will be false if 
            `ena_in` is False
        Parm:
            R: the decimation ratio
    '''
    countSize=2**np.ceil(np.log2(R))
    count=Signal(intbv(0, max=countSize, min=0))
    
    @always(clk.posedge)
    def PassControl():
        if rst:
            y.next=0
        else:
            if count==0:
                y.next=x
                ena_out.next=True
            else:
                y.next=0
                ena_out.next=False
        
    @always(clk.posedge)
    def CountControl():
        if rst:
            count.next=0
        else:
            if count==R-1:
                count.next=0
            else:
                count.next=count+1
    
    return instances()

Testing


In [38]:
Peeker.clear()

x=Signal(modbv(1)[BitWidth:]); Peeker(x, 'x')
y=Signal(modbv(0)[BitWidth:]); Peeker(y, 'y')

ena_in, ena_out, clk, rst=[Signal(bool(0)) for  _ in range(4)]
Peeker(ena_in, 'ena_in'); Peeker(ena_out, 'ena_out'); Peeker(clk, 'clk'); Peeker(rst, 'rst')

DUT=Decimator(x, y, ena_in, ena_out, clk, rst, R=2)

def Integrator_TB():
    
    @always(delay(1))  ## delay in nano seconds
    def clkGen():
        clk.next = not clk
        
    @instance
    def stimulus():
        Tested_ena=False
        Tested_rst=False
        count=0
        while 1:
            
            if Tested_ena==False and count<=2:
                print(f'Tested_ena: {Tested_ena}, Tested_rst:{Tested_rst}, count:{count}')
            elif Tested_ena==False and count>2:
                print(f'Tested_ena: {Tested_ena}, Tested_rst:{Tested_rst}, count:{count}')

                ena_in.next=True
                Tested_ena=True
            
            if Tested_ena and Tested_rst==False:
                print(f'Tested_ena: {Tested_ena}, Tested_rst:{Tested_rst}, count:{count}')

                rst.next=True
                Tested_rst=True
            elif Tested_ena and Tested_rst and  count<=4:
                print(f'Tested_ena: {Tested_ena}, Tested_rst:{Tested_rst}, count:{count}')

                rst.next=False
                Tested_rst=True
                x.next=1
            
            if Tested_ena and Tested_rst and count>4:
                x.next=x+1
            
            if count> 2*BitWidth:
                raise StopSimulation
            count+=1
            yield clk.posedge
                
                
            
    return instances()
sim = Simulation(DUT, Integrator_TB(), *Peeker.instances()).run()


Tested_ena: False, Tested_rst:False, count:0
Tested_ena: False, Tested_rst:False, count:1
Tested_ena: False, Tested_rst:False, count:2
Tested_ena: False, Tested_rst:False, count:3
Tested_ena: True, Tested_rst:False, count:3
Tested_ena: True, Tested_rst:True, count:4

In [39]:
Peeker.to_wavedrom(start_time=0, stop_time=40, tock=True)


To Verilog


In [40]:
x=Signal(modbv(1)[BitWidth:])
y=Signal(modbv(0)[BitWidth:])

ena_in, ena_out, clk, rst=[Signal(bool(0)) for  _ in range(4)]

toVerilog(Decimator, x, y, ena_in, ena_out, clk, rst, R=2)
VerilogTextReader('Decimator');


***Verilog modual from Decimator.v***

 // File: Decimator.v
// Generated by MyHDL 0.9.0
// Date: Mon Feb 26 19:24:54 2018


`timescale 1ns/10ps

module Decimator (
    x,
    y,
    ena_in,
    ena_out,
    clk,
    rst
);
// A decimation (down sampling) section for a CIC filter
// 
// Inputs:
//     x (data): the x(n) data in feed
//     ------------------------
//     ena_in (bool): the exstiror calc hold input. calc is done only if 
//     `ena_in` is True
//     
//     clk(bool): clock feed
//     rst(bool): reset feed
// 
// Outputs:
//     y (data):  the y(n) output 
//     ----------------------
//     ena_out: the exstior calc hold output. will be false if 
//     `ena_in` is False
// Parm:
//     R: the decimation ratio

input [31:0] x;
output [31:0] y;
reg [31:0] y;
input ena_in;
output ena_out;
reg ena_out;
input clk;
input rst;

reg [0:0] count;





always @(posedge clk) begin: DECIMATOR_COUNTCONTROL
    if (rst) begin
        count <= 0;
    end
    else begin
        if (($signed({1'b0, count}) == (2 - 1))) begin
            count <= 0;
        end
        else begin
            count <= (count + 1);
        end
    end
end


always @(posedge clk) begin: DECIMATOR_PASSCONTROL
    if (rst) begin
        y <= 0;
    end
    else begin
        if ((count == 0)) begin
            y <= x;
            ena_out <= 1'b1;
        end
        else begin
            y <= 0;
            ena_out <= 1'b0;
        end
    end
end

endmodule

** ToVerilogWarning: Port is not used: ena_in

Interpolator

Theory

$$y(n)=\sum_{k=-\infty}^{\infty}x(k)\delta(n-kR)$$

In [41]:
InterpolatorTheory=X.subs(z, exp(1j*DisAng*R)); InterpolatorTheory


Out[41]:
$$X{\left (e^{1.0 i \Omega R} \right )}$$

myHDL implementation


In [42]:
def Interpolator(x, y, ena_in, ena_out,  clk, rst, R=8):
    '''
        A interpolation section for a CIC filter
        
        Inputs:
            x (data): the x(n) data in feed
            ------------------------
            ena_in (bool): the exstiror calc hold input. calc is done only if 
            `ena_in` is True
            
            clk(bool): clock feed
            rst(bool): reset feed
        
        Outputs:
            y (data):  the y(n) output of y(n)=y(n-1)+x(n)
            ----------------------
            ena_out: the exstior calc hold output. will be false if 
            `ena_in` is False
        Parm:
            R: the up-sampleing ratio
    '''
    countSize=2**np.ceil(np.log2(R))
    count=Signal(intbv(0, max=countSize, min=0))
    
    @always(clk.posedge)
    def PassControl():
        if rst:
            y.next=0
        else:
            if ena_in:
                y.next=x
                ena_out.next=True
            
            elif count>0:
                y.next=0
                ena_out.next=True
            
            else:
                y.next=0
                ena_out.next=False
        
        
    @always(clk.posedge)
    def CountControl():
        if rst:
            count.next=0
        else:
            if ena_in:
                count.next=R-1
            elif count>0:
                count.next=count+1
    
    
    
    return instances()

muHDL Testing


In [43]:
Peeker.clear()

x=Signal(modbv(1)[BitWidth:]); Peeker(x, 'x')
y=Signal(modbv(0)[BitWidth:]); Peeker(y, 'y')

ena_in, ena_out, clk, rst=[Signal(bool(0)) for  _ in range(4)]
Peeker(ena_in, 'ena_in'); Peeker(ena_out, 'ena_out'); Peeker(clk, 'clk'); Peeker(rst, 'rst')

DUT=Interpolator(x, y, ena_in, ena_out, clk, rst, R=2)

def Integrator_TB():
    
    @always(delay(1))  ## delay in nano seconds
    def clkGen():
        clk.next = not clk
        
    @instance
    def stimulus():
        Tested_ena=False
        Tested_rst=False
        count=0
        while 1:
            
            if Tested_ena==False and count<=2:
                print(f'Tested_ena: {Tested_ena}, Tested_rst:{Tested_rst}, count:{count}')
            elif Tested_ena==False and count>2:
                print(f'Tested_ena: {Tested_ena}, Tested_rst:{Tested_rst}, count:{count}')

                ena_in.next=True
                Tested_ena=True
            
            if Tested_ena and Tested_rst==False:
                print(f'Tested_ena: {Tested_ena}, Tested_rst:{Tested_rst}, count:{count}')

                rst.next=True
                Tested_rst=True
            elif Tested_ena and Tested_rst and  count<=4:
                print(f'Tested_ena: {Tested_ena}, Tested_rst:{Tested_rst}, count:{count}')

                rst.next=False
                Tested_rst=True
                x.next=1
            
            if Tested_ena and Tested_rst and count>4:
                x.next=x+1
            
            if count> 2*BitWidth:
                raise StopSimulation
            count+=1
            yield clk.posedge
                
                
            
    return instances()
sim = Simulation(DUT, Integrator_TB(), *Peeker.instances()).run()


Tested_ena: False, Tested_rst:False, count:0
Tested_ena: False, Tested_rst:False, count:1
Tested_ena: False, Tested_rst:False, count:2
Tested_ena: False, Tested_rst:False, count:3
Tested_ena: True, Tested_rst:False, count:3
Tested_ena: True, Tested_rst:True, count:4

In [44]:
Peeker.to_wavedrom(start_time=0, stop_time=40, tock=True)


To Verilog


In [45]:
x=Signal(modbv(1)[BitWidth:])
y=Signal(modbv(0)[BitWidth:])

ena_in, ena_out, clk, rst=[Signal(bool(0)) for  _ in range(4)]

toVerilog(Interpolator, x, y, ena_in, ena_out, clk, rst, R=2)
VerilogTextReader('Interpolator');


***Verilog modual from Interpolator.v***

 // File: Interpolator.v
// Generated by MyHDL 0.9.0
// Date: Mon Feb 26 19:25:18 2018


`timescale 1ns/10ps

module Interpolator (
    x,
    y,
    ena_in,
    ena_out,
    clk,
    rst
);
// A interpolation section for a CIC filter
// 
// Inputs:
//     x (data): the x(n) data in feed
//     ------------------------
//     ena_in (bool): the exstiror calc hold input. calc is done only if 
//     `ena_in` is True
//     
//     clk(bool): clock feed
//     rst(bool): reset feed
// 
// Outputs:
//     y (data):  the y(n) output of y(n)=y(n-1)+x(n)
//     ----------------------
//     ena_out: the exstior calc hold output. will be false if 
//     `ena_in` is False
// Parm:
//     R: the up-sampleing ratio

input [31:0] x;
output [31:0] y;
reg [31:0] y;
input ena_in;
output ena_out;
reg ena_out;
input clk;
input rst;

reg [0:0] count;





always @(posedge clk) begin: INTERPOLATOR_COUNTCONTROL
    if (rst) begin
        count <= 0;
    end
    else begin
        if (ena_in) begin
            count <= (2 - 1);
        end
        else if ((count > 0)) begin
            count <= (count + 1);
        end
    end
end


always @(posedge clk) begin: INTERPOLATOR_PASSCONTROL
    if (rst) begin
        y <= 0;
    end
    else begin
        if (ena_in) begin
            y <= x;
            ena_out <= 1'b1;
        end
        else if ((count > 0)) begin
            y <= 0;
            ena_out <= 1'b1;
        end
        else begin
            y <= 0;
            ena_out <= 1'b0;
        end
    end
end

endmodule

Pass Through

myHDL implementation


In [46]:
def PassThrough(x, y, ena_in, ena_out):
    '''
        A pass-throug (do nothing) section for a CIC filter
        
        Inputs:
            x (data): the x(n) data in feed
            ------------------------
            ena_in (bool): the exstiror calc hold input. calc is done only if 
            `ena_in` is True
        
        Outputs:
            y (data):  the y(n) output of y(n)=y(n-1)+x(n)
            ----------------------
            ena_out: the exstior calc hold output. will be false if 
            `ena_in` is False
    '''
    @always_comb
    def logic():
        y.next=x
        ena_out.next=ena_in
    return logic

myHDL Testing


In [47]:
Peeker.clear()

x=Signal(modbv(1)[BitWidth:]); Peeker(x, 'x')
y=Signal(modbv(0)[BitWidth:]); Peeker(y, 'y')

ena_in, ena_out, clk=[Signal(bool(0)) for  _ in range(3)]
Peeker(ena_in, 'ena_in'); Peeker(ena_out, 'ena_out'); Peeker(clk, 'clk')

DUT=PassThrough(x, y, ena_in, ena_out)

def Integrator_TB():
    
    @always(delay(1))  ## delay in nano seconds
    def clkGen():
        clk.next = not clk
        
    @instance
    def stimulus():
        count=0
        while 1:
            if count<=5:
                ena_in.next=True
            elif count<=10:
                ena_in.next=False
            elif count>=15:
                ena_in.next=True
            
            if count> 2*BitWidth:
                raise StopSimulation
            x.next=x+1
            count+=1
            yield clk.posedge
                
                
            
    return instances()
sim = Simulation(DUT, Integrator_TB(), *Peeker.instances()).run()

In [48]:
Peeker.to_wavedrom(start_time=0, stop_time=40, tock=True)


To Verilog


In [49]:
x=Signal(modbv(1)[BitWidth:])
y=Signal(modbv(0)[BitWidth:])

ena_in, ena_out, clk=[Signal(bool(0)) for  _ in range(3)]

toVerilog(PassThrough, x, y, ena_in, ena_out)
VerilogTextReader('PassThrough');


***Verilog modual from PassThrough.v***

 // File: PassThrough.v
// Generated by MyHDL 0.9.0
// Date: Mon Feb 26 19:26:23 2018


`timescale 1ns/10ps

module PassThrough (
    x,
    y,
    ena_in,
    ena_out
);
// A pass-throug (do nothing) section for a CIC filter
// 
// Inputs:
//     x (data): the x(n) data in feed
//     ------------------------
//     ena_in (bool): the exstiror calc hold input. calc is done only if 
//     `ena_in` is True
// 
// Outputs:
//     y (data):  the y(n) output of y(n)=y(n-1)+x(n)
//     ----------------------
//     ena_out: the exstior calc hold output. will be false if 
//     `ena_in` is False

input [31:0] x;
output [31:0] y;
wire [31:0] y;
input ena_in;
output ena_out;
wire ena_out;







assign y = x;
assign ena_out = ena_in;

endmodule

Complete CIC Filter

Theory


In [50]:
N=symbols('N')
CIC=simplify(((1-z**(-R*M))**N)/((1-z**(-1))**N)); CIC


Out[50]:
$$\left(1 - \frac{1}{z}\right)^{- N} \left(1 - z^{- M R}\right)^{N}$$

In [51]:
CICsub=simplify(CIC.subs(zFunc.lhs, zFunc.rhs)); CICsub


Out[51]:
$$\left(1 - \frac{1}{r} e^{- 1.0 i \Omega}\right)^{- N} \left(1 - \left(r e^{1.0 i \Omega}\right)^{- M R}\right)^{N}$$

In [52]:
CICN=lambdify((z, M, R, N), CIC, dummify=False)
def CICEx(N=2, M=2, R=2):
    Mvalue=M; Rvalue=R; Nvalue=N
    HzN=CICN(zN, M=Mvalue, R=Rvalue, N=Nvalue); HzN.shape
    HzNMag=np.abs(HzN); HzNPhase=np.angle(HzN)

    HAtR1=zFuncN(rN, AngThetaN)
    HzAtR1N=CICN(zAtR1, M=Mvalue, R=Rvalue, N=Nvalue)
    HzAtR1NMag=np.abs(HzAtR1N); HzAtR1NPhase=np.angle(HzAtR1N)
    Zplot(zR, zI, HzNMag, HzAtR1NMag, HzNPhase, HzAtR1NPhase, 
         f'CIC Dec of N={Nvalue}, M={Mvalue}, R={Rvalue}')
CICEx()


myHDL implementation


In [53]:
def CICFilter(x, y, ena_in, ena_out, clk, rst, N=3, M=2, R=8, Type=None):
    '''
        The complet CIC filter
        
        Inputs:
            x (data): the x(n) data in feed
            ------------------------
            ena_in (bool): the exstiror calc hold input. calc is done only if 
            `ena_in` is True
            
            clk(bool): clock feed
            rst(bool): reset feed
        
        Outputs:
            y (data):  the y(n) output of y(n)=y(n-1)+x(n)
            ----------------------
            ena_out: the exstior calc hold output. will be false if 
            `ena_in` is False
        Parm:
            N: the number of stages
            M: the Z delay order
            R: the decimation/Interpolation ratio
            Type (None, 'Dec', 'Interp'): type of CIC filter

    '''
    #Parmters for sizeing the 2's comp data wires
    #assumes len(x)==len(y)
    WordLen_1=len(x)-1
    WireGuage=2**WordLen_1
    
    
    
    #------------------------------------------------
    #create the wires from the interpoltor (or lack of) to the comb sec
    #data wire
    Interp_Comb_DWire=Signal(intbv(0, min=-WireGuage, max=WireGuage))
    #enable wire
    Interp_Comp_EWire=Signal(bool(0))

    
    #instatiniat the interpolator (or lack of)
    if Type=='Interp':
        #                   x, y,                 ena_in, ena_out,       clk, rst, R
        Interp=Interpolator(x, Interp_Comb_DWire, ena_in, Interp_Comp_EWire, clk, rst, R)
    else:
                          #x, y, ena_in, ena_out  
        Interp=PassThrough(x, Interp_Comb_DWire, ena_in, Interp_Comp_EWire)
    
    #------------------------------------------------------------
    
    #Data Wires
    Comb_DWireIJ=[Signal(intbv(0, min=-WireGuage, max=WireGuage)) for i in range(N)]
    #Enable Wires
    Comb_EWireIJ=[Signal(bool(0)) for i in range(N)]
    
    #instatintte the comb sections and wire them
    Comb_i=[]
    for i in range(N):
        if i==0:
            #                  x,                 y,                ena_in,            ena_out, clk, rst, M
            Comb_i.append(Comb(Interp_Comb_DWire, Comb_DWireIJ[i] , Interp_Comp_EWire, Comb_EWireIJ[i], clk, rst, M))
        else:
            #                  x,                 y,               ena_in,            ena_out,         clk, rst, M
            Comb_i.append(Comb(Comb_DWireIJ[i-1], Comb_DWireIJ[i], Comb_EWireIJ[i-1], Comb_EWireIJ[i], clk, rst, M))
    
    
    #------------------------------------------------------------
    #Data Wires
    Integrator_DWireIJ=[Signal(intbv(0, min=-WireGuage, max=WireGuage)) for i in range(N)]
    #Enable Wires
    Integrator_EWireIJ=[Signal(bool(0)) for i in range(N)]

    #instatintte the integrator sections and wire them
    Integrtor_i=[]
    for i in range(N):
        if i==0:
            #                             x,                 y,                     ena_in, ena_out,               clk, rst
            Integrtor_i.append(Integrator(Comb_DWireIJ[N-1], Integrator_DWireIJ[i], Comb_EWireIJ[N-1], Integrator_EWireIJ[i], clk, rst))
        else:
            #                             x,                       y,                     ena_in,                  ena_out,               clk, rst
            Integrtor_i.append(Integrator(Integrator_DWireIJ[i-1], Integrator_DWireIJ[i], Integrator_EWireIJ[i-1], Integrator_EWireIJ[i], clk, rst))

    
    
    #-------------------------------------------------------------
    #instatiniat the decimator (or lack of)
    if Type == 'Dec':
        #             x,                       y, ena_in,                  ena_out, clk, rst, R
        Dec=Decimator(Integrator_DWireIJ[N-1], y, Integrator_EWireIJ[N-1], ena_out, clk, rst, R)
    else:
        #               x,                       y, ena_in,                  ena_out
        Dec=PassThrough(Integrator_DWireIJ[N-1], y, Integrator_EWireIJ[N-1], ena_out)
    
    return instances()

myHDL Testing

(Need to come up with a test bench)

Chris: Would a square unit pulse be the best test of this

To Verilog


In [54]:
x=Signal(modbv(1)[BitWidth:])
y=Signal(modbv(0)[BitWidth:])

ena_in, ena_out, clk, rst=[Signal(bool(0)) for  _ in range(4)]

toVerilog(CICFilter, x, y, ena_in, ena_out, clk, rst, N=3, M=2, R=8, Type=None)

VerilogTextReader('CICFilter');


***Verilog modual from CICFilter.v***

 // File: CICFilter.v
// Generated by MyHDL 0.9.0
// Date: Mon Feb 26 19:27:06 2018


`timescale 1ns/10ps

module CICFilter (
    x,
    y,
    ena_in,
    ena_out,
    clk,
    rst
);
// The complet CIC filter
// 
// Inputs:
//     x (data): the x(n) data in feed
//     ------------------------
//     ena_in (bool): the exstiror calc hold input. calc is done only if 
//     `ena_in` is True
//     
//     clk(bool): clock feed
//     rst(bool): reset feed
// 
// Outputs:
//     y (data):  the y(n) output of y(n)=y(n-1)+x(n)
//     ----------------------
//     ena_out: the exstior calc hold output. will be false if 
//     `ena_in` is False
// Parm:
//     N: the number of stages
//     M: the Z delay order
//     R: the decimation/Interpolation ratio
//     Type (None, 'Dec', 'Interp'): type of CIC filter

input [31:0] x;
output [31:0] y;
wire [31:0] y;
input ena_in;
output ena_out;
wire ena_out;
input clk;
input rst;

wire Interp_Comp_EWire;
wire signed [31:0] Interp_Comb_DWire;
reg signed [31:0] Dec_x;
reg Dec_ena_in;
reg signed [31:0] Integrtor_i_2_x;
reg Integrtor_i_2_ena_in;
reg signed [31:0] Integrtor_i_1_x;
reg Integrtor_i_1_ena_in;
reg signed [31:0] Integrtor_i_0_x;
reg Integrtor_i_0_ena_in;
reg signed [31:0] Comb_i_2_x;
reg Comb_i_2_ena_in;
reg signed [31:0] Comb_i_2_subx;
reg signed [31:0] Comb_i_2_Zdelay_i_1_x;
reg signed [31:0] Comb_i_1_x;
reg Comb_i_1_ena_in;
reg signed [31:0] Comb_i_1_subx;
reg signed [31:0] Comb_i_1_Zdelay_i_1_x;
reg signed [31:0] Comb_i_0_subx;
reg signed [31:0] Comb_i_0_Zdelay_i_1_x;





always @(posedge clk) begin: CICFILTER_COMB_I_0_ZDELAY_I_0_LOGIC
    if (Interp_Comp_EWire) begin
        Comb_i_0_Zdelay_i_1_x <= Interp_Comb_DWire;
    end
end


always @(posedge clk) begin: CICFILTER_COMB_I_0_ZDELAY_I_1_LOGIC
    if (Interp_Comp_EWire) begin
        Comb_i_0_subx <= Comb_i_0_Zdelay_i_1_x;
    end
end


always @(posedge clk) begin: CICFILTER_COMB_I_0_LOGC
    if (rst) begin
        Comb_i_1_x <= 0;
    end
    else begin
        if (Interp_Comp_EWire) begin
            Comb_i_1_x <= (Interp_Comb_DWire - Comb_i_0_subx);
            Comb_i_1_ena_in <= 1'b1;
        end
        else begin
            Comb_i_1_ena_in <= 1'b0;
        end
    end
end


always @(posedge clk) begin: CICFILTER_COMB_I_1_ZDELAY_I_0_LOGIC
    if (Comb_i_1_ena_in) begin
        Comb_i_1_Zdelay_i_1_x <= Comb_i_1_x;
    end
end


always @(posedge clk) begin: CICFILTER_COMB_I_1_ZDELAY_I_1_LOGIC
    if (Comb_i_1_ena_in) begin
        Comb_i_1_subx <= Comb_i_1_Zdelay_i_1_x;
    end
end


always @(posedge clk) begin: CICFILTER_COMB_I_1_LOGC
    if (rst) begin
        Comb_i_2_x <= 0;
    end
    else begin
        if (Comb_i_1_ena_in) begin
            Comb_i_2_x <= (Comb_i_1_x - Comb_i_1_subx);
            Comb_i_2_ena_in <= 1'b1;
        end
        else begin
            Comb_i_2_ena_in <= 1'b0;
        end
    end
end


always @(posedge clk) begin: CICFILTER_COMB_I_2_ZDELAY_I_0_LOGIC
    if (Comb_i_2_ena_in) begin
        Comb_i_2_Zdelay_i_1_x <= Comb_i_2_x;
    end
end


always @(posedge clk) begin: CICFILTER_COMB_I_2_ZDELAY_I_1_LOGIC
    if (Comb_i_2_ena_in) begin
        Comb_i_2_subx <= Comb_i_2_Zdelay_i_1_x;
    end
end


always @(posedge clk) begin: CICFILTER_COMB_I_2_LOGC
    if (rst) begin
        Integrtor_i_0_x <= 0;
    end
    else begin
        if (Comb_i_2_ena_in) begin
            Integrtor_i_0_x <= (Comb_i_2_x - Comb_i_2_subx);
            Integrtor_i_0_ena_in <= 1'b1;
        end
        else begin
            Integrtor_i_0_ena_in <= 1'b0;
        end
    end
end



assign Interp_Comb_DWire = x;
assign Interp_Comp_EWire = ena_in;


always @(posedge clk) begin: CICFILTER_INTEGRTOR_I_0_LOGIC
    if (rst) begin
        Integrtor_i_1_x <= 0;
    end
    else begin
        if (Integrtor_i_0_ena_in) begin
            Integrtor_i_1_x <= (Integrtor_i_1_x + Integrtor_i_0_x);
            Integrtor_i_1_ena_in <= 1'b1;
        end
        else begin
            Integrtor_i_1_ena_in <= 1'b0;
        end
    end
end


always @(posedge clk) begin: CICFILTER_INTEGRTOR_I_1_LOGIC
    if (rst) begin
        Integrtor_i_2_x <= 0;
    end
    else begin
        if (Integrtor_i_1_ena_in) begin
            Integrtor_i_2_x <= (Integrtor_i_2_x + Integrtor_i_1_x);
            Integrtor_i_2_ena_in <= 1'b1;
        end
        else begin
            Integrtor_i_2_ena_in <= 1'b0;
        end
    end
end


always @(posedge clk) begin: CICFILTER_INTEGRTOR_I_2_LOGIC
    if (rst) begin
        Dec_x <= 0;
    end
    else begin
        if (Integrtor_i_2_ena_in) begin
            Dec_x <= (Dec_x + Integrtor_i_2_x);
            Dec_ena_in <= 1'b1;
        end
        else begin
            Dec_ena_in <= 1'b0;
        end
    end
end



assign y = Dec_x;
assign ena_out = Dec_ena_in;

endmodule